package com.flyqiu.common.transaction;

import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

/**
 * 流程事务管理
 */
public interface FlyQiuTransactionManage {


    /**
     * 应用事务有返回值
     *
     * @param apply 事务应用函数
     * @param <T>   返回数据类型
     * @return 返回数据
     */
    default <T> T apply(FlyQiuTransactionApplyResult<T> apply) {
        return apply(apply, new DefaultTransactionDefinition());
    }

    /**
     * 应用事务 有返回值
     *
     * @param apply                 事务应用函数
     * @param transactionDefinition 事务定义
     * @param <T>                   返回数据类型
     * @return 返回数据
     */
    default <T> T apply(FlyQiuTransactionApplyResult<T> apply, TransactionDefinition transactionDefinition) {
        TransactionStatus transaction = begin(transactionDefinition);
        boolean newTransaction = transaction.isNewTransaction();
        try {
            T result = apply.apply();
            if (!newTransaction) {
                return result;
            }
            commit(transaction);
            return result;
        } catch (Exception e) {
            rollback(transaction);
            throw new RuntimeException(e);
        }
    }


    /**
     * 应用事务 无返回值
     *
     * @param apply 事务应用函数
     */
    default void apply(FlyQiuTransactionApply apply) {
        apply(apply, new DefaultTransactionDefinition());
    }

    /**
     * 应用事务 无返回值
     *
     * @param apply                 事务应用函数
     * @param transactionDefinition 事务定义
     */
    default void apply(FlyQiuTransactionApply apply, TransactionDefinition transactionDefinition) {

        TransactionStatus transaction = begin(transactionDefinition);
        boolean newTransaction = transaction.isNewTransaction();
        try {
            apply.apply();
            if (!newTransaction) {
                return;
            }
            commit(transaction);
        } catch (Exception e) {
            rollback(transaction);
            throw new RuntimeException(e);
        }
    }

    /**
     * 开启事务
     *
     * @return 事务状态
     */
    default TransactionStatus begin() {
        return begin(new DefaultTransactionDefinition());
    }

    /**
     * 开启事务
     *
     * @param transactionDefinition 事务定义
     * @return 事务状态
     */
    TransactionStatus begin(TransactionDefinition transactionDefinition);

    /**
     * 提交事务
     *
     * @param transactionStatus 事务状态
     */
    void commit(TransactionStatus transactionStatus);

    /**
     * 回滚事务
     *
     * @param transactionStatus 事务状态
     */
    void rollback(TransactionStatus transactionStatus);


}
